using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using Microsoft.Practices.CompositeWeb.Utility;

namespace CompositeWeb.Extensions.Configuration
{
    /// <summary>
    /// A collection of <see cref="ModuleConfigurationElement"/>.
    /// </summary>
    public class CustomModuleConfigurationElementCollection : ConfigurationElementCollection
    {
        /// <summary>
        /// Initializes a new instance of <see cref="ModuleConfigurationElementCollection"/>.
        /// </summary>
        public CustomModuleConfigurationElementCollection()
        {
        }

        /// <summary>
        /// Initializes a new <see cref="ModuleConfigurationElementCollection"/>.
        /// </summary>
        /// <param name="modules">The initial set of <see cref="ModuleConfigurationElement"/>.</param>
        public CustomModuleConfigurationElementCollection(CustomModuleConfigurationElement[] modules)
        {
            Guard.ArgumentNotNull(modules, "modules");
            foreach (CustomModuleConfigurationElement module in modules)
            {
                BaseAdd(module);
            }
        }


        /// <summary>
        /// Indicates that an exception should be raised if a duplicate element is found.
        /// </summary>
        protected override bool ThrowOnDuplicate
        {
            get { return true; }
        }

        /// <summary>
        /// Adds a <see cref="ModuleConfigurationElement"/> to the collection.
        /// </summary>
        /// <param name="module">A <see cref="ModuleConfigurationElement"/> instance.</param>
        public void Add(CustomModuleConfigurationElement module)
        {
            BaseAdd(module);
        }

        /// <summary>
        /// Tests if the collection contains the configuration for the specified module name.
        /// </summary>
        /// <param name="moduleName">The name of the module to search the configuration for.</param>
        /// <returns><see langword="true"/> if a configuration for the module is present; otherwise <see langword="false"/>.</returns>
        public bool Contains(string moduleName)
        {
            return base.BaseGet(moduleName) != null;
        }

        /// <summary>
        /// Searches the collection for all the <see cref="ModuleConfigurationElement"/> that match the specified predicate.
        /// </summary>
        /// <param name="match">A <see cref="Predicate{T}"/> that implements the match test.</param>
        /// <returns>A <see cref="List{ModuleConfigurationElement}"/> with the successful matches.</returns>
        public List<CustomModuleConfigurationElement> FindAll(Predicate<CustomModuleConfigurationElement> match)
        {
            List<CustomModuleConfigurationElement> found = new List<CustomModuleConfigurationElement>();
            foreach (CustomModuleConfigurationElement moduleElement in this)
            {
                if (match(moduleElement))
                {
                    found.Add(moduleElement);
                }
            }
            return found;
        }

        /// <summary>
        /// Gets the type of <see cref="ConfigurationElementCollectionType"/>.
        /// </summary>
        public override ConfigurationElementCollectionType CollectionType
        {
            get { return ConfigurationElementCollectionType.BasicMap; }
        }

        /// <summary>
        /// Gets the name to identify this collection in the configuration.
        /// </summary>
        protected override string ElementName
        {
            get { return "module"; }
        }

        /// <summary>
        /// Creates a new <see cref="ModuleConfigurationElement"/>.
        /// </summary>
        /// <returns>A <see cref="ModuleConfigurationElement"/>.</returns>
        protected override ConfigurationElement CreateNewElement()
        {
            return new CustomModuleConfigurationElement();
        }

        /// <summary>
        /// Gets the element key for specified element.
        /// </summary>
        /// <param name="element">The <see cref="ConfigurationElement"/> to get the key for.</param>
        /// <returns>An <see langword="object"/>.</returns>
        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((CustomModuleConfigurationElement)element).Name;
        }

        /// <summary>
        /// Gets the <see cref="ModuleConfigurationElement"/> located at the specified index in the collection.
        /// </summary>
        /// <param name="index">The index of the element in the collection.</param>
        /// <returns>A <see cref="ModuleConfigurationElement"/>.</returns>
        public CustomModuleConfigurationElement this[int index]
        {
            get { return (CustomModuleConfigurationElement)base.BaseGet(index); }
        }
    }
}